/*
 *  main.js, create main user interface and initilize the app.
 */
/**Add Three variable used for Load Ontology Dialog*/
var dialog_onto;
var dialog_remote;
var dialog_local;

/** Internet Explorer menu patch. */
function hoverRollOverFactory(elm) {
    return function() {
        /* backup original className. */
        elm.origClassName = elm.className;
        var newClassName = elm.className;
        newClassName += "Hover";
        newClassName = newClassName.replace(/\s/g, "Hover ");
        newClassName += " hover";
        elm.className = elm.className + " " + newClassName;
    }
}

function hoverRollOffFactory(elm) {
    return function() {
        elm.className = elm.origClassName;
    }
}

/**
 *  create menu bar, and attach associated actions.
 * related color and style, "css/menu.css".
 */
function createMenu() {
    globalVar.menu = new OAT.Menu();
    globalVar.menu.noCloseFilter = "noclose";
    globalVar.menu.createFromUL("menu");
    // Internet Explorer needs some tricks.
    if (OAT.Browser.isIE) {
	    var root = $("menu");
	    for (var i = 0; i < root.children.length; i++) {
	        OAT.Dom.attach(root.children[i], "mouseover", hoverRollOverFactory(root.children[i]));
	        OAT.Dom.attach(root.children[i], "mouseout", hoverRollOffFactory(root.children[i]));
            var element = root.children[i].children[0];
            if (element == undefined || !element.children == undefined)
                continue;
	        for (var j = 0; j < element.children.length; j++) {
		        OAT.Dom.attach(element.children[j], "mouseover", hoverRollOverFactory(element.children[j]));
		        OAT.Dom.attach(element.children[j], "mouseout", hoverRollOffFactory(element.children[j]));
                var elms = element.children[j].children[0];
                if (elms == undefined || elms.children == undefined)
                    continue;
                for (var k = 0; k < elms.children.length; k++) {
                    OAT.Dom.attach(elms.children[k], "mouseover", hoverRollOverFactory(elms.children[k]));
                    OAT.Dom.attach(elms.children[k], "mouseout", hoverRollOffFactory(elms.children[k]));
                }
	        }
	    }
    }
    // attach actions to the menu.
    OAT.Dom.attach("menu_new_project", "click", newProject);
    OAT.Dom.attach("menu_edit_uri", "click", editUri);
    OAT.Dom.attach("menu_edit_name", "click", editName);
    OAT.Dom.attach("menu_delete", "click", deleteElement);
    OAT.Dom.attach("menu_open_mp", "click", openMappingFile);
    OAT.Dom.attach("menu_open_dbres", "click", catalogOption);
    OAT.Dom.attach("menu_open_onto", "click", loadRDF);
    OAT.Dom.attach("menu_close_project", "click", closeProject);
    OAT.Dom.attach("menu_view_isparql", "click", queryWithiSPARQL);
    OAT.Dom.attach("menu_close_db", "click", closeDbView);
    OAT.Dom.attach("menu_close_onto", "click", closeOntoView);
    OAT.Dom.attach("menu_tool_prefix", "click", prefixManage);
    OAT.Dom.attach("menu_tool_url_rewrite", "click", configUrlRewrite);
    OAT.Dom.attach("menu_view_dbres", "click", showDbres);
    OAT.Dom.attach("menu_view_onto", "click", showOnto);
    OAT.Dom.attach("menu_view_mu", "click", showAllMappingUnits);
    OAT.Dom.attach("menu_save", "click", saveMapping);
    OAT.Dom.attach("menu_view_sql", "click", saveMappingFileToDisk);
    OAT.Dom.attach("menu_generate", "click", generate);
    OAT.Dom.attach("menu_help_help", "click", help);
    OAT.Dom.attach("menu_help_about", "click", about);
}

/**
 * return callback function when drag a table to the cnavas.
 */
function dragTableCallback(table) {
    return function addMappingTable(target, x, y) {
        var mt = new MappingTable(table, statistic.mappingTable);
        statistic.mappingTable++;
        mt.draw(x, y);
        globalVar.gdOnto.addTarget(mt.content);
        globalVar.mappingTables.push(mt);
    }
}

/**
 * return callback function whe drag a column to a property.
 */
function dragColumnCallback(column) {
    return function addMappingColumn(target, x, y) {
        var mp = target.belong;
        var mc = new MappingColumn(column, statistic.mappingColumn);
        statistic.mappingColumn++;
        mp.setMappingColumn(mc);
    }
}

/**
 * create data resource registry view window, colors and styles are setted in "css/view.css".
 */
function DbResView() {
    var self = this;
    self.show = false;
    var width = Math.round(document.body.clientWidth / 5);
    var totalHeight = (document.body.clientHeight > 0) ? document.body.clientHeight : document.documentElement.clientHeight;
    var height = Math.round((totalHeight - 26) / 2);
    if (height < 100) {
        height = Math.round(screen.height / 3);
    }
    var win = new OAT.Window({close:0, min:0, max:0, x:0, y: 0, width:width, height:height, title:"Database Schema", margentsH:2 }, OAT.WindowData.TYPE_AUTO);
    var base = OAT.Dom.create("div", {}, "viewBase");
    var treeUl = OAT.Dom.create("ul");
    var treeView = new OAT.Tree({imagePath:"images/",  onClick:"select", onDblClick:"toggle"});
    treeView.assign(treeUl, true);

    this.insertDb = function(db) {
        if (db.type !== "DataSource")
            return;
        var node = treeView.tree.createChild(db.uri, true);
        return node;
    };

    this.insertTable = function(dbNode, table) {
        if (table.type !== "Table")
            return;
        var tableNode = dbNode.createChild(table.name, true);
        globalVar.gdTable.addSource(tableNode._gdElm, false, dragTableCallback(table));
        return tableNode;
    }

    this.insertColumn = function(tableNode, column) {
        if (column.type !== "Column")
            return;
        var columnNode = tableNode.createChild(column.name);
        globalVar.gdColumn.addSource(columnNode._gdElm, false, dragColumnCallback(column));
    }

    this.addColumn = function(tbNode, column, progress) {
        var columnNode = tbNode.createChild(column.name);
        globalVar.gdColumn.addSource(columnNode._gdElm, false, dragColumnCallback(column));
        progress.update(1);
    }

    // add a dbres into tree view.
    this.addDb = function(dbs) {
        if (dbs.length <= 0 || statistic.table < 1)
            return;
        interval.total = 0;
        var p = "There is (are) " + statistic.table + " table(s), it may take a few minutes, be patient please.";
        var progress = new ProgressMonitor(p, statistic.column);
        progress.show();
        for (var k = 0; k < dbs.length; k++) {
            var db = dbs[k];
            var node = treeView.tree.createChild(db.uri);
            var tableNode = null;
            var tables = db.tables;
            for (var i = 0; i < tables.length; i++) {
                tableNode = node.createChild(tables[i].name);
                var columns = tables[i].columns;
                for (var j = 0; j < columns.length; j++) {
                    interval.total += interval.loop;
                    setTimeout(bind(self.addColumn, [ tableNode,columns[j],progress ]), interval.total);
                }
                globalVar.gdTable.addSource(tableNode._gdElm, false, dragTableCallback(tables[i]));
                tableNode.collapse();
            }
        }
    }

    // clear dbres view
    this.clear = function() {
        var children = treeView.tree.children;
        for (var i = children.length; i > 0; i--) {
            treeView.tree.deleteChild(children[i - 1]);
        }
    }
    base.appendChild(treeUl);
    win.content.appendChild(base);
    $("viewLayout").appendChild(win.div);
}

/**
 * return callback function when drag a ontology to a mapping table.
 */
function dragOntoCallback(onto) {
    return function(target, x, y) {
        var mt = target.belong;
        var mo = new MappingOnto(onto, statistic.mappingOnto);
        statistic.mappingOnto++;
        mt.addMappingOnto(mo);
        var otherOnto = false;
        for (var i = 0; i < globalVar.mappingTables.length; i++) {
            for (var j = 0; j < globalVar.mappingTables[i].mappingOntos.length; j++) {
                otherOnto = globalVar.mappingTables[i].mappingOntos[j].ontology;
                if (!otherOnto)
                    continue;
                var re = false;
                if (onto.isObject(otherOnto)) { 
                    re = new Relation(mo, globalVar.mappingTables[i].mappingOntos[j], globalVar.relationCount++);
                    re.propUri = onto.getRelationProp(otherOnto);
                } else if (otherOnto.isObject(onto)) {
                    re = new Relation(globalVar.mappingTables[i].mappingOntos[j], mo, globalVar.relationCount);
                    re.propUri = otherOnto.getRelationProp(onto);
                }
                if (re) {
                    globalVar.relationCount++;
                    if (!onto.equals(otherOnto)) {
                        mo.addRelation(re);
                        globalVar.mappingTables[i].mappingOntos[j].addRelation(re);
                    } else {
                        mo.addRelation(re);
                    }
                    re.draw();
                }
            }
        }
        globalVar.gdProperty.addTarget(mo.content);
        configIRI(mo);
    }
}

/**
 * return callback function when drag a property to a mapping ontology.
 */
function dragPropertyCallback(property) {
    return function(target, x, y) {
        var mo = target.belong;
        var mp = new MappingProperty(property, statistic.mappingProperty);
        statistic.mappingProperty++;
        mo.addMappingProperty(mp);
        globalVar.gdColumn.addTarget(mp.content);
    }
}

/**
 * create ontology schema view window, color and style are setted in "css/view.css".
 */
function OntoSchemaView() {
    var self = this;
    var width = Math.round(document.body.clientWidth / 5);
    var totalHeight = (document.body.clientHeight > 0) ? document.body.clientHeight : document.documentElement.clientHeight;
    var height = Math.round((totalHeight - 26) / 2);
    if (height < 100) {
        height = Math.round(screen.height / 3);
    }
    var win = new OAT.Window({close:0, min:0, max:0, x:0, y: height, width:width, height:height, title:"Ontology Schema", margentsH:2 }, OAT.WindowData.TYPE_AUTO);
    var base = OAT.Dom.create("div", {}, "viewBase");
    var treeView = new OAT.Tree({imagePath:"images/",  onClick:"select", onDblClick:"toggle"});
    var treeUl = OAT.Dom.create("ul");
    treeView.assign(treeUl, true);

    this.insertOnto = function(onto) {
        if (onto.type !== "Ontology")
            return;
        var ontoNode = treeView.tree.createChild(onto.name, true);
        globalVar.gdOnto.addSource(ontoNode._gdElm, false, dragOntoCallback(onto));
        return ontoNode;
    }

    this.insertProperty = function(ontoNode, property) {
        if (property.type !== "Property")
            return;
        var propNode = ontoNode.createChild(property.name);
        globalVar.gdProperty.addSource(propNode._gdElm, false, dragPropertyCallback(property));
    }

    this.addProperty = function(ontoNode, prop, progress) {
        var propNode = ontoNode.createChild(prop.name);
        globalVar.gdProperty.addSource(propNode._gdElm, false, dragPropertyCallback(prop));
        progress.update(1);
    };

    
    this.addOnto = function(ontos) {
        interval.total = 0;
        if (statistic.ontology < 1) {
            return;
        }
        var p = "There is (are) " + statistic.ontology + " ontology(ies), it may take a few minutes, be patient please.";
        var progress = new ProgressMonitor(p, statistic.property);
        progress.show();
        for (var i = 0; i < ontos.length; i++) {
            var onto = ontos[i];
            var node = treeView.tree.createChild(onto.name);
            globalVar.gdOnto.addSource(node._gdElm, false, dragOntoCallback(onto));
            var properties = onto.properties;
            for (var j = 0; j < properties.length; j++) {
                if (properties[j].isValue) {
                    interval.total += interval.loop;
                    setTimeout(bind(self.addProperty, [node, properties[j], progress]), interval.total);
                }
            }
            node.collapse();
        }
    }

    this.clear = function() {
        var children = treeView.tree.children;
        for (var i = children.length; i > 0; i--) {
            treeView.tree.deleteChild(children[i - 1]);
        }
    }

    base.appendChild(treeUl);
    win.content.appendChild(base);
    $("viewLayout").appendChild(win.div);
}

function ProgressMonitor(prompt, total) {
    var self = this;
    this.total = total;
    this.current = 0;
    $("progress_prompt").innerHTML = prompt;
    this.update = function(delta) {
        self.current += delta;
        var value = Math.round(self.current * 100 / self.total);
        $("progress_bar").style.width = value + "%";
        $("progress_bar").innerHTML = value + "%";
        if (self.current >= self.total) {
            self.hide();
            $("progress_bar").style.width = "0%";
            $("progress_bar").innerHTML = "0%";
        }
    };
    this.show = function() {
        OAT.Dom.hide(globalVar.canvas);
        $("progress").style.display = "";
        OAT.Dom.center("progress", 1, 1);
    };
    this.hide = function() {
        $("progress").style.display = "none";
        $("progress_bar").style.width = "0%";
        $("progress_bar").style.innerHTML = "0%";
        OAT.Dom.show(globalVar.canvas);
    };
}

/**
 * open ontology schema file.
 */
function openOntoFile() {
    var openOnto = OAT.Dom.create("div");
    dialogs.openOnto = new OAT.Dialog("Open ontology schema...", openOnto, {width:500,modal:1,buttons:1});
    alert(opts.path);
    dialogs.openOnto.cancel = dialogs.openOnto.hide;
    dialogs.openOnto.show();
}

function help() {
    window.open("./help.html");
}

/**
 * initilization, executed when html page is loaded.
 */
function init() {
    createMenu();
    globalVar.canvas = $("canvas");
    var height = (document.body.clientHeight > 0)? document.body.clientHeight : document.documentElement.clientHeight;
    globalVar.canvas.style.height = height - 26;
    globalVar.gdTable = new OAT.GhostDrag();
    globalVar.gdTable.addTarget(globalVar.canvas);
    globalVar.gdColumn = new OAT.GhostDrag();
    globalVar.gdOnto = new OAT.GhostDrag();
    globalVar.gdProperty = new OAT.GhostDrag();
    globalVar.dbView = new DbResView();
    globalVar.ontoView = new OntoSchemaView();
    OAT.Dom.hide(globalVar.canvas);
    OAT.Dom.attach(globalVar.canvas, "click", function(event) {
        if (globalVar.selectElement) {
            globalVar.selectElement.deselect();
            globalVar.selectElement = false;
        }
        if (event.stopPropagation)
	        event.stopPropagation();
	    else
	        event.cancelBubble = true;
    });
    
    
    dialog_onto = new OAT.Dialog("load_onto","load_onto",{modal:1,buttons:0,width:400});
    OAT.Event.attach("remote","click",remote_f);
    OAT.Event.attach("default","click",default_f);
    OAT.Event.attach("local","click",local_f);
    
    dialog_remote = new OAT.Dialog("remote_onto","remote_onto",{modal:1,buttons:1,width:400});
    dialog_remote.ok = function(){remote_f2(remote_uri.value);};
    dialog_remote.cancel = function(){dialog_remote.hide();};
    
    dialog_local = new OAT.Dialog("local_onto","local_onto",{modal:1,buttons:0,width:450});
    OAT.Event.attach("local_open","click",local_f2);
}
